# -*- coding: utf-8 -*-
"""
@Time    : 2024/6/21 12:46 
@Author  : ZhangShenao 
@File    : http_server.py 
@Desc    : Http服务器
"""
import os

from flask import Flask
from flask_cors import CORS
from flask_migrate import Migrate

from config import Config
from internal.exception import CustomException
from internal.router import Router
from pkg.response import success, HttpResponse, json, HttpStatusCode
from pkg.sqlalchemy import SQLAlchemy


# Http服务器,继承Flask类
class HttpServer(Flask):
    """
    Http服务器
    """

    def __init__(self,
                 *args,
                 conf: Config,
                 db: SQLAlchemy,
                 migrate: Migrate,
                 router: Router,
                 **kwargs):
        """
        构造函数
        :param args:
        :param conf: Flask应用配置
        :param db: 数据库
        :param migrate: 数据库迁移工具
        :param router: 路由器
        """
        # 调用父类的构造函数
        super().__init__(*args, **kwargs)

        # 初始化应用配置
        self.config.from_object(conf)

        # 初始化数据库
        db.init_app(self)

        # 初始化数据库迁移工具
        migrate.init_app(self, db, directory='internal/migrations')

        # 注册异常处理函数
        self.register_error_handler(Exception, self._register_error_handler)

        # 注册路由
        router.register_route(self)

        # CORS跨域设置
        CORS(self, resources={
            r'/*': {
                'origins': '*',  # 允许的请求来源
                'supports_credentials': True,  # 允许跨域请求携带授权凭证信息
                'methods': ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],  # 允许的请求方法
                'allow_headers': ['Content-Type', 'Authorization', 'Accept'],  # 允许的请求头
                'expose_headers': ['Content-Type', 'Authorization', 'Accept']  # 允许暴露的响应头
            }
        })

    def _register_error_handler(self, error: Exception):
        """
        注册错误处理函数
        :param error: 错误类型
        """
        # 针对自定义业务异常,返回通用响应信息
        if isinstance(error, CustomException):
            return success(data=error.data if error.data is not None else {})
        # 其他类型异常,可能是数据库、网络、第三方中间件等原因
        # 如果是在开发环境,则直接抛出异常完整信息,方便调试
        if self.debug or os.getenv("FLASK_ENV") == "dev":
            raise error

        # 在生产环境,返回通用响应信息,提升用户体验
        return json(data=HttpResponse(code=HttpStatusCode.FAIL,
                                      message=str(error),
                                      data={}))
